#pragma once
#include"sock.hpp"
#include"Protocol.hpp"
#include"Log.hpp"
#include"Err.hpp"


#include<iostream>
#include<string>
#include<unistd.h>

namespace CalcClient
{
    class TcpClient
    {
        public:
        TcpClient(const std::string& ip,const uint16_t& port)
        :_server_ip(ip),_server_port(port)
        {}

        void Init()
        {
            _sock.Socket();
        }
        void Start()
        {
            int i = 5;
            while(i > 0)
            {
                if(_sock.Connect(_server_ip,_server_port) != -1)
                 break;
                
                 logMessage(Warning,"Connect Server Fail! %d",i--);
                 sleep(1);
            }
            if(i == 0)
            {
                logMessage(Fatal,"Connect Server Fail!");
                exit(CONNECT_ERR);
            }

            // 执行读写函数
           ServiceIO();
        }

        void ServiceIO()
        {
            while(true)
            {
                std::string str;
                std::cout<<"Please Enter:> ";
                std::getline(std::cin,str);

                // 1. 判断是否需要退出
                if(str == "quit")
                 break;

                // 2. 分割输入的字符串
                my_protocol::Request req;
                [&]()
                {
                    std::string ops = "+-*%";
                    int pos = 0;
                    for(auto e :ops)
                    {
                        pos = str.find(e);
                        if(pos != std::string::npos)
                        break; // 合法情况
                        
                    }

                    req._x = Util::StrToInt(str.substr(0,pos));
                    req._y = Util::StrToInt(str.substr(pos+1));
                    req._op = str[pos];
                }();

                // 3. 序列化
                std::string sendMsg;
                req.Serialization(&sendMsg);

                // 4. 添加报头
                my_protocol::AddHeader(sendMsg);

                // 5. 发送数据
                send(_sock.GetSock(),sendMsg.c_str(),sendMsg.size(),0);

                // 6. 获取数据
                std::string inBuff;
                std::string package;
                int len = 0;
                while(true)
                {
                
                    len = my_protocol::ReadPackage(_sock.GetSock(),inBuff,&package);
                    if(len < 0)
                    exit(READ_ERR);
                    else if(len > 0)
                    break;
                }

                // 7. 移除报头
                my_protocol::RemoveHeader(package,len);

                // 8. 反序列化
                my_protocol::Response resp;
                if(resp.Deserialization(package) == false)
                {
                    logMessage(Warning,"Deserialization Fail!");
                    continue;
                }

                // 9. 获取结果
                std::cout << "The Result: " << resp._result << " " << resp._code << endl;

            }
        }

        ~TcpClient()
        {
            _sock.Close();
        }
        
        private:
        Sock _sock;
        std::string _server_ip;
        uint16_t _server_port;
    };
}